组件库打包 umd 发布

最近有个需求是将原本在项目内使用的组件文件夹打包发布的 npm,之后直接从 npm 安装使用。不再作为项目的代码。
接到需求,本以为是十分简单的任务,直接配置下 webpack,将打包输出格式改为 umd 打包,再发布的 npm 不就大功告成了吗?
但是在实际的实践中发现还是有些坑的。

一、打包

umd 文件的好处是可以同时支持多种引入方式,自动判断现在的环境来决定代码的导出方式。比如用 script 标签引入的话,代码会被挂载到 window 对象, require 方式的话会以 module.exports 的方式导出等。
首先就是配置下 webpack 的配置文件。

1
2
3
4
5
6
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].min.js'),
library: 'skel',
libraryTarget: 'umd
}

将 libraryTarget 设置为 umd, library 指定插件的名称,这样就可以愉快的进行打包了。当然也可以设置 externals 将第三方库的文件排除,减小插件库的体积。为了方便测试,建议先不要加 externals,可以后期测试通过再加。
那么包打包出来了,怎么测试呢?首先,我们可以把打包出来的代码直接复制下来,粘贴到浏览器控制台(前提打包时没配置 externals,并且包不能过大,致使浏览器卡死),然后回车。这样我们打包后的代码就在浏览器上运行了,这时我们从 window 对象中查找有没有 skel (插件名)这个属性。当然也可以自己写段代码验证下,这样就没有了之前的两个限制。
我查看时发现window 对象有 skel 这个属性,但是值为 undefined,这说明我打的包出了问题。于是又去看 webpack 配置,并没有发现什么问题。于是找最终原因找了很长时间。
偶然我删除了将 node_modules 包单独打包出 vendor 的配置,发现 skel 为 undefined 的问题解决了。所以打包umd 时建议将第三方的库使用 externals 排除,不要打包到 vendor。

二、发布

打包完后,接着就是使用 npm publish 命令发布了,发布时 package.json 文件有几项需要注意的配置:
1. main(入口文件一定要写打包后的 umd 文件)

  1. name 写插件名
    三、验证
    发布到 npm 后,我就试着验证了下是否可以直接在项目内使用。
    首先我先删除了原来的组件库文件夹,及 webpack 对该文件夹目录配置的别名。
    然后使用 npm 安装已发布的组件库。
    因为之前都是使用的别名 skel 来引入的组件,所以现在使用 npm 安装 skel 后,之前的引入代码不用改。
    接着启动项目。。。。。。。。。。。。
    本以为可以正常启动,访问页面,结果出现下面的报错。

    image.png
    看到报错,第一反应就是 Object.keys 传入了 null 或者 undefined,于是去插件项目下全局查找 Object.keys 并打印它的传参(方法有些笨,不过还有效),然后运行了写插件项目的测试 demo,在页面发现打印出了上图打印的信息, Transition 组件的 propTypes 为 undefined。去查看组件代码并未发现什么错误,最终发现是 transform-react-remove-prop-types 这个插件的锅,再生产环境打包时把代码里的 propTypes 给移除了,导致遍历 key 时找不到而报错。于是我配置了下 ignoreName 将 Transition 文件排除,不移除该文件的 propTypes。
    再次打包,然后直接将打包后的文件代码复制到项目 node_modules 下插件下的 skel.min.js 覆盖下,然后重启项目,果然,错误消失了。
    但却来了新的警告,唉,头大。。。

    image.png
    网上大致搜了下,应该是引入的第三方库使用的是 es5 的 react 代码写法。
    在已安装的依赖中,找到了两个依赖觉得可能是造成这个警告的原因, react-hot-loader 和 react-router, 在react-router 的压缩文件中搜了下确实搜到了 getDefaultProps , 于是将react-router 放到 externals 再打包,再复制,再重启项目,页面渲染成功,哈哈,欣喜。

插件打包没啥问题了,重新发布公司的 npm 一下。